#include <iostream>
#include <vector>
#include <string>
#include <map>
#include <set>
#include <list>
using namespace std;

class InternetSecurity {
private:
    typedef set<string> TDic;

    struct TSite {
        int Idx;
        string Address;
        vector<string> Words;

        TSite() : Idx(-1) {}
        TSite(int idx, string address) : Idx(idx), Address(address) {}
    };

    typedef list<TSite> TSites;

    TSites::iterator FindBadSite(TSites &sites, const TDic &badWords, int threshold) const {
        int found = 0;
        for (TSites::iterator it = sites.begin(); it != sites.end(); ++it) {
            for (vector<string>::const_iterator wordIter = it->Words.begin(); wordIter != it->Words.end(); ++wordIter)
                if (badWords.find(*wordIter) != badWords.end())
                    if(++found >= threshold)
                        return it;
        }
        return sites.end();
    }
public:
    vector<string> determineWebsize(vector<string> address, vector<string> keyword, vector<string> dangerous, int threshold) {
        TDic badWords;
        for (vector<string>::const_iterator it = dangerous.begin(); it != dangerous.end(); ++it)
            badWords.insert(*it);
       
        TSites sites;
        const size_t N = address.size();
        for (int i = 0; i < N; ++i) {
            TSite site(i, address[i]);
            string keyWord = keyword[i];
            string tmp;

            for (string::const_iterator it = keyWord.begin(); it != keyWord.end(); ++it) {
                if (*it == ' ') {
                    site.Words.push_back(tmp);
                    tmp = "";
                } else
                    tmp += *it;
            }

            if (!tmp.empty())
                site.Words.push_back(tmp);
            sites.push_back(site);
        }

        typedef map<int, TSite> TBadSites;
        TBadSites badSites;

        for(;;) {
            TSites::iterator badSiteIter = FindBadSite(sites, badWords, threshold);
            if (badSiteIter == sites.end())
                break;
            badSites[badSiteIter->Idx] = *badSiteIter;
            for (vector<string>::const_iterator wordIter = badSiteIter->Words.begin(); wordIter != badSiteIter->Words.end(); ++wordIter)
                badWords.insert(*wordIter);
            sites.erase(badSiteIter);
        }

        vector<string> res;
        for (TBadSites::const_iterator it = badSites.begin(); it != badSites.end(); ++it)
            res.push_back(it->second.Address);
        return res;
    }
};

int main() {
    cout << "<<<test>>>" << endl;

    vector<string> address;
        address.push_back("www.topcoder.com");
        address.push_back("www.sindicate_of_evil.com");
        address.push_back("www.happy_citizens.com");
    vector<string> keyword;
        keyword.push_back("hack encryption decryption internet algorithm");
        keyword.push_back("signal interference evil snake poison algorithm");
        keyword.push_back("flower baloon topcoder blue sky sea");
    vector<string> dangerous;
        dangerous.push_back("hack");
        dangerous.push_back("encryption");
        dangerous.push_back("decryption");
        dangerous.push_back("interference");
        dangerous.push_back("signal");
        dangerous.push_back("internet");
    int threshold = 3;

    InternetSecurity is;
    vector<string> res = is.determineWebsize(address, keyword, dangerous, threshold);
    cout << "Result: " << endl;
    for (vector<string>::const_iterator it = res.begin(); it != res.end(); ++it)
        cout << *it << endl;
    return 0;
}
